#!/usr/bin/python
#imports
import mwclient
import re
import os, sys, shutil
import tarfile
import hashlib
import tempfile

# Get the title of the section ==FileName.xyz==
# and everything between the <source*> </source> tag
def GetCode(S):
    reg = re.compile(r"==([\w ]*?\.[\w ]*?)==.*?<source.*?>(.*?)</source>.*?", re.DOTALL)
    return [(x.strip('\n'), y.strip('\n')) for (x,y) in reg.findall(S)]

def GetVTKCMake(S):
    reg = re.compile(r"\{\{(VTKCMakeLists)\|(.*?)\}\}.*?", re.DOTALL)
    return [reg.findall(S)]

def GetVTKQtCMake(S):
    reg = re.compile(r"\{\{(VTKQtCMakeLists)\|(.*?)\}\}.*?", re.DOTALL)
    return [reg.findall(S)]

# Extact the CMakeLists.txt portion of a wiki template
# everything between | and |
def ExtractCMakeLists(S):
    reg = re.compile(r'\|(.*?)\|', re.DOTALL).search(S)
    return [reg.group(1)]

# Fill in the template parameters in a CMakeLists template file
# The output is a CMakeLists.txt file with Name substituted for {{{1}}}
def FillCMakeLists(S, Name):
    reg = re.sub(r'\{\{{1\}\}\}', Name, S)
    return reg

def FillQtCMakeLists(S, Name):
    reg = re.sub(r'\{\{{2\}\}\}', Name, S)
    return reg

# Connect to the wiki
site = mwclient.Site(('https','itk.org'), '/Wiki/')

# Read the Wiki Templates
VTKTemplateFile = open("Admin/VTKCMakeLists", 'r')
VTKTemplate = VTKTemplateFile.read();
VTKTemplateFile.close()

VTKQtTemplateFile = open("Admin/VTKQtCMakeLists", 'r')
VTKQtTemplate = VTKQtTemplateFile.read();
VTKQtTemplateFile.close()

# Update the Wik1i Templates if they have changed
print "Updating wiki templates..."
for t in site.allpages(namespace='10'):
    if t.name == "Template:VTKQtCMakeLists":
        if (hashlib.md5(VTKQtTemplate).digest() != hashlib.md5(t.edit()+"\n").digest()):
            print "   Admin/VTKQtCMakeLists has changed"
            VTKQtTemplate = t.edit()+"\n";
            VTKQtTemplateFile = open("Admin/VTKQtCMakeLists", 'w')
            VTKQtTemplateFile.write(VTKQtTemplate);
            VTKQtTemplateFile.close()
        else:
            print "   Admin/VTKQtCMakeLists not changed"
    elif t.name == "Template:VTKCMakeLists":
        if (hashlib.md5(VTKTemplate).digest() != hashlib.md5(t.edit()+"\n").digest()):
            print "   Admin/VTKCMakeLists has changed"
            VTKTemplate = t.edit()+"\n";
            VTKTemplateFile = open("Admin/VTKCMakeLists", 'w')
            VTKTemplateFile.write(VTKTemplate);
            VTKTemplateFile.close()
        else:
            print "   Admin/VTKCMakeLists not changed"

# Make the reference mtime to be the most recent of the two CMakeLists templates
refStat1 = os.stat("Admin/VTKQtCMakeLists")
refStat2 = os.stat("Admin/VTKCMakeLists")
refMtime = refStat1.st_mtime
if refStat2.st_mtime > refStat1.st_mtime:
    refMtime = refStat2.st_mtime

# Create a dict to hold code name and page name
codeToPage = dict()

# Create a dict to hold CMakeLists.txt file
exampleToCMake = dict()

# Create a dict to hold the file names for each example
exampleToFileNames = dict()

# Get list of all pages
xxx = 0
for page in site.pages:
    # Look for find pages that start with VTK/Examples/
    to_find = "VTK/Examples/"
    start = page.name.find(to_find)

    # If the page doesn't start with VTK/Examples, skip it
    if start < 0:
        continue

    # Get the part of the page name that comes after VTK/Examples/
    # e.g. if the page name is VTK/Examples/GeometricObjects/Line, 
    # ExamplePath will be GeometriObjects/Line
    ExamplePath = page.name[start+len(to_find):]

    # Continuing the above example, the below splits GeometricObjects/Line
    # into PathName = GeometricObjects/
    # ExampleName = Line
    PathSplit = os.path.split(ExamplePath)
    PathName = PathSplit[0]
    ExampleName = re.sub(" ", "_", PathSplit[1])

    # Get the content of the page
    content = page.edit()

    # Get all of the file names and file content on the page
    CodeChunks = GetCode(content)

    vtkQtCMakeChunks = GetVTKQtCMake(content)
    if vtkQtCMakeChunks[0]:
        exampleToCMake[ExampleName] = FillCMakeLists(ExtractCMakeLists(VTKQtTemplate)[0], ExampleName)
        xxx = xxx + 1

    vtkCMakeChunks = GetVTKCMake(content)
    if vtkCMakeChunks[0]:
        exampleToCMake[ExampleName] = FillCMakeLists(ExtractCMakeLists(VTKTemplate)[0], ExampleName)
        xxx = xxx + 1
    if CodeChunks:
        for code in CodeChunks:
            # Extract the Level 2 heading (e.g. ==Line.cxx==) into FileName and the content in the first <source ...> tag below the heading into FileContent
            FileName = code[0]
            FileContent = code[1]
            if FileName == "CMakeLists.txt":
                break
            if FileName ==" CMakeLists.txt ":
                continue
            if FileName == " CmakeLists.txt":
                continue
            if FileName == "CmakeLists.txt":
                continue

            # Check if the path exists, if not, create it
            if not os.path.exists(PathName):
                if PathName != "":
                    os.makedirs(PathName)
            # Write the source code file
            OutputFile = "./" + PathName + "/" + FileName
            if os.path.exists(OutputFile):
                sys.exit("ERROR: " + OutputFile + " already exists. Check for duplicate file in examples.")
            print "Creating " + OutputFile
            MyFile = open(OutputFile, 'w')
            MyFile.write(FileContent)
            MyFile.write("\n")
            MyFile.close()
            codeToPage[FileName] = ExamplePath
            # Store the full file names for the example
            if ExampleName not in exampleToFileNames:
                exampleToFileNames[ExampleName] = set()
            exampleToFileNames[ExampleName].add(OutputFile)
        if xxx > 10000:
            break
# Create tarballs for each example
tmpDir = tempfile.mkdtemp(prefix="VTKTarballs") + "/"

# Create the Tarballs directory in the source tree if not present
# If it does not exist, assume the tarball repo has not been cloned
# and we need to ignore tar files
if not os.path.exists("Tarballs"):
    os.makedirs("Tarballs")
    ignoreFile = open("Tarballs/.gitignore", 'w')
    ignoreFile.write("*,tar\n")
    ignoreFile.close()

# Create tarballs
# For each example page, create a directory and copy that example's files
# into the directory
# If the example has a CMakeLists.txt file, copy that.
# Also, create a subdir called build. This directory is handy when you want to
# configure with CMake and build the example.
for example in exampleToFileNames:
    if example not in exampleToCMake:
        continue
    # Make the directories for the example
    srcDir = tmpDir + example
    codeFileName = srcDir + "/" + example + ".cxx"
    if not os.path.exists(srcDir):
        os.makedirs(srcDir)
        os.makedirs(srcDir + "/build")

        # An example may have multiple source files
        for exampleFileName in exampleToFileNames[example]:
            # Get the file name
            tarFileName = srcDir + "/" + os.path.split(exampleFileName)[1]
            # Copy the code for the example
            shutil.copy(exampleFileName,tarFileName)
            os.utime(tarFileName,(refMtime,refMtime))

    # Some examples do not have a CMakeLists.txt file
    if example in exampleToCMake:
        cmakeFileName = srcDir + "/" + "CMakeLists.txt"
        cmakeFile = open(cmakeFileName, 'w')
        cmakeFile.write(exampleToCMake[example])    
        cmakeFile.close()
        os.utime(cmakeFileName,(refMtime,refMtime))

    # Set the mtimes for the directories containing the example
    # Since the mtime is stored in the tar header for each file and directory,
    # we need a consistent time so that a tar of an unchanged example will be equal
    # to the one in the repo
    os.utime(srcDir,(refMtime,refMtime))
    os.utime(srcDir + "/build",(refMtime,refMtime))

    # Now create the tar file for the example
    # The tarballs are stored in the source tree
    tar = tarfile.open("Tarballs/" + example + ".tar", "w")
    tar.add(srcDir,arcname=example)
    tar.close()

os.utime(tmpDir,(0,refMtime))
# Cleanup the temporary directories
shutil.rmtree(tmpDir)

# Generate an html page that links each example code file to its Wiki Example
# page
indexFile = open('./ExampleCodeToWikiPage.html', 'w')
indexFile.write("Navigate to the page that contains the source code of an example<br>");
indexFile.write("\n");
sortedByCode = sorted(codeToPage.items())
for item in sortedByCode:
    indexFile.write("<A HREF=http://vtk.org/Wiki/VTK/Examples/" + re.sub(" ", "_", item[1]) + ">" + item[0] + "</A>")
    indexFile.write("<br>\n")
indexFile.close()
